`timescale    1ps/1ps
module s8_main_ctrl_01(
    input  wire        resetb,
    input  wire        sclk,
    input  wire        time_1s,
    input  wire        init_end,
    input  wire        ext_d_ok,
    input  wire [15:0] ext_addr,
    input  wire [15:0] set_addr,
    input  wire [7:0]  set_data,
        
    //模式控制
    output reg         init_mode,
    output reg         reboot_en,
    output reg         comm_en,
    output reg         reconfig_en,
    output reg  [1:0]  reboot_sel,
    output reg         reconfig_adjust_en,
    output reg         reconfig_pll_en,

    //Flash 状态寄存器控制
    output reg         read_flash_status_L,
    output reg         enable_flash_swp,
    output reg         disable_flash_swp,

    //
    output wire [7:0]  tout
);

//************************************************/
//        参数定义
//************************************************/
//*************state******************************
parameter  IDLE_STATE        = 4'h01;
parameter  INIT_STATE        = 4'h02;
parameter  WAIT_STATE        = 4'h04;
parameter  NOMAL_STATE       = 4'h08;

//**********************************************/
//        信号定义
/************************************************/
reg  [3:0]  main_state;
reg         init_start;
reg  [2:0]  init_st_count;
reg         init_end_dly;
reg         enable_flash_swp_dly;
reg         disable_flash_swp_dly;
reg         reconfig_en_dly;
reg         reconfig_adjust_en_dly;
reg         reconfig_pll_en_dly;

reg         reboot_flag;
reg  [1:0]  reboot_cnt;
reg         reboot_en_tmp;

//************************************************/
//        状态控制
//************************************************/
//**************状态机*******************
always@(posedge sclk or negedge resetb)
    if(resetb == 0)
        main_state <= IDLE_STATE;
    else 
        case (main_state)
            IDLE_STATE:
                if(init_start==1'b1)
                    main_state<=INIT_STATE;
            INIT_STATE:
                if (init_end==1)
                    main_state<=WAIT_STATE;
            WAIT_STATE:
                main_state<=NOMAL_STATE;
            NOMAL_STATE:
                main_state<=NOMAL_STATE;
            default: 
                main_state<=IDLE_STATE;
        endcase                
            
//************************************************/
//        信号选通
//************************************************/
always@(posedge sclk or negedge resetb)
    if(resetb == 0)
        init_st_count<=0;
    else if(main_state==IDLE_STATE && init_st_count[2]==0)
        init_st_count<=init_st_count+1'b1;

always@(posedge sclk)
    if(main_state!=IDLE_STATE)
        init_start<=1'b0;
    else if(init_st_count==3'h3)
        init_start<=1'b1;
                
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        init_mode<=0;
    else if (main_state==INIT_STATE)
        init_mode<=1;
    else
        init_mode<=0;
        
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en_tmp<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h1000)
        reboot_en_tmp<=1;
        
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en<=1'b0;
    else
        reboot_en<=reboot_en_tmp&&reboot_flag;

always@(posedge sclk or negedge resetb)
    if(resetb == 0)
        comm_en<=0;
    else if (main_state==WAIT_STATE || main_state==NOMAL_STATE)
        comm_en<=1;
    else
        comm_en<=0;

//************************************************/
//        reboot保护
//************************************************/
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_flag <= 1'b0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0005)
        reboot_flag <= 1'b1;
    else if (reboot_cnt == 1'b0)
        reboot_flag <= 1'b0;
end

always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_cnt <= 1'b0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0005)
        reboot_cnt <= 2'd3;
    else if (time_1s && reboot_cnt != 1'b0)
        reboot_cnt <= reboot_cnt - 1'b1;
end

//************************************************/
//        Flash状态寄存器
//************************************************/
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        read_flash_status_L<=0;
    else if (read_flash_status_L)
        read_flash_status_L<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0000)
        read_flash_status_L<=set_data[0];
 
//always@(posedge sclk or negedge resetb)
//    if (resetb == 0)
//        read_flash_status_H<=0;
//    else if (read_flash_status_H)
//        read_flash_status_H<=0;
//    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0001)
//        read_flash_status_H<=set_data[0];

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        enable_flash_swp<=0;
    else if (enable_flash_swp_dly)
        enable_flash_swp<=0;
    else if (!init_end_dly && init_end)
        enable_flash_swp<=1'b1;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0002)
        enable_flash_swp<=set_data[0];

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        enable_flash_swp_dly <= 1'b0;
    else
        enable_flash_swp_dly <= enable_flash_swp;

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        disable_flash_swp<=0;
    else if (disable_flash_swp_dly)
        disable_flash_swp<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0003)
        disable_flash_swp<=set_data[0];

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        disable_flash_swp_dly <= 1'b0;
    else
        disable_flash_swp_dly <= disable_flash_swp;

always @(posedge sclk or negedge resetb)
    if (resetb == 0)
        init_end_dly <= 1'b0;
    else
        init_end_dly <= init_end;

//************************************************/
//        reconfig_en状态寄存器
//************************************************/
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reconfig_en<=0;
    else if (reconfig_en_dly)
        reconfig_en<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0004)
        reconfig_en<=set_data[0];

always @(posedge sclk or negedge resetb)
    if (resetb == 0)
        reconfig_en_dly <= 1'b0;
    else
        reconfig_en_dly <= reconfig_en;

//************************************************/
//      reboot_sel
//************************************************/
always @(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_sel <= 1'b0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0005)
        reboot_sel <= set_data[1:0];

//************************************************/
//        reconfig_adjust_en
//************************************************/
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reconfig_adjust_en <=0;
    else if (reconfig_adjust_en_dly)
        reconfig_adjust_en<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0006)
        reconfig_adjust_en<=set_data[0];

always@(posedge sclk)
    reconfig_adjust_en_dly <= reconfig_adjust_en;

//************************************************/
//        reconfig_pll_en
//************************************************/
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reconfig_pll_en <=0;
    else if (reconfig_pll_en_dly)
        reconfig_pll_en<=0;
    else if (ext_d_ok == 1 && ext_addr[15:0] == 16'h0100 && set_addr[15:0] == 16'h0007)
        reconfig_pll_en<=set_data[0];

always@(posedge sclk)
    reconfig_pll_en_dly <= reconfig_pll_en;

/************************************************/
//        测试信号
/************************************************/
assign tout={init_end,main_state};

endmodule        
